package com.spring.reader;

import com.spring.annotation.*;
import com.spring.bean.BeanDefinition;
import com.spring.enums.ScopeType;
import com.spring.util.ClassUtils;
import com.spring.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author ljj
 */
@Slf4j
public class ComponentScanAnnotationParser {
	/**
	 * 已扫描包路径集合
	 */
	private final Set<String> scanedPaths = new HashSet<>();
	
	/**
	 * 已扫描class集合
	 */
	private final Set<Class<?>> scanedClasses = new HashSet<>();
	
	
	/**
	 * 解析扫描注解
	 */
	public List<BeanDefinition> parse(Class<?> configurationClass) {
		List<BeanDefinition> bds = new ArrayList<>(16);
		String scanPackagePath = configurationClass.getAnnotation(ComponentScan.class).value();
		
		if (StringUtils.isEmpty(scanPackagePath)) {
			scanPackagePath = configurationClass.getPackage().getName();
		}
		
		log.info("扫描 {} 包路径",scanPackagePath);
		
		// 该路径已经扫描过了
		if (scanedPaths.contains(scanPackagePath)) {
			log.warn("包路径 {} 已经扫描过了", scanPackagePath);
			return bds;
		}
		scanedPaths.add(scanPackagePath);
		
		// 扫描目标包下面的所有class
		List<Class<?>> classes = ClassUtils.scan(scanPackagePath);
		
		// 筛选出指定的类
		for (Class<?> clazz : classes) {
			if (scanedClasses.contains(clazz)) {
				continue;
			}
			scanedClasses.add(clazz);
			
			if (isComponent(clazz)) {
				BeanDefinition bd = new BeanDefinition();
				bd.setBeanName(getBeanName(clazz));
				bd.setBeanClass(clazz);
				bd.setScope(getBeanScope(clazz));
				bds.add(bd);
			}
		}
		return bds;
	}
	
	private ScopeType getBeanScope(Class<?> clazz) {
		Scope scope = clazz.getAnnotation(Scope.class);
		return scope == null ? ScopeType.SINGLE : scope.value();
	}
	
	
	/**
	 * 这个类是否是 希望放进容器的 component
	 */
	public boolean isComponent(Class<?> clazz) {
		return clazz.isAnnotationPresent(Component.class) ||
				clazz.isAnnotationPresent(Controller.class) ||
				clazz.isAnnotationPresent(Service.class) ||
				clazz.isAnnotationPresent(Configuration.class);
	}
	
	/**
	 * 取Component  Controller  Service  注解上面的bean名字
	 */
	public String getBeanName(Class<?> clazz) {
		String name = "";
		if (clazz.isAnnotationPresent(Component.class)) {
			name = clazz.getAnnotation(Component.class).value();
		} else if (clazz.isAnnotationPresent(Controller.class)) {
			name = clazz.getAnnotation(Controller.class).value();
		} else if (clazz.isAnnotationPresent(Service.class)) {
			name = clazz.getAnnotation(Service.class).value();
		}
		
		// name 默认空，如果注解没有写名字，则用 类名首字母小写作为名字
		if ("".equals(name)) {
			name = StringUtils.toLowerFirstCase(clazz.getSimpleName());
		}
		return name;
	}
}
